/*
 * Copyright (C) 2024, Ingenic Semiconductor Co.,Ltd.
 * Author: Keven <keven.ywhan@ingenic.com>
 */

#ifndef __MSC_H__
#define __MSC_H__

#define MSC_OFF						0x10000
/**
 * MSC Register Offset
 */
#define MSC_BLOCKSIZE_R(n)				((n) * MSC_OFF + 0x4)
#define MSC_BLOCKCOUNT_R(n)				((n) * MSC_OFF + 0x6)
#define MSC_ARGUMENT_R(n)				((n) * MSC_OFF + 0x8)
#define MSC_XFER_MODE_R(n)				((n) * MSC_OFF + 0xc)
#define MSC_CMD_R(n)					((n) * MSC_OFF + 0xe)
#define MSC_RESP01_R(n)					((n) * MSC_OFF + 0x10)
#define MSC_RESP23_R(n)					((n) * MSC_OFF + 0x14)
#define MSC_RESP45_R(n)					((n) * MSC_OFF + 0x18)
#define MSC_RESP67_R(n)					((n) * MSC_OFF + 0x1c)
#define MSC_BUF_DATA_R(n)				((n) * MSC_OFF + 0x20)
#define MSC_PSTATE_REG(n)				((n) * MSC_OFF + 0x24)
#define MSC_BGAP_CTRL_R(n)				((n) * MSC_OFF + 0x2a)
#define MSC_CLK_CTRL_R(n)				((n) * MSC_OFF + 0x2c)
#define MSC_TOUT_CTRL_R(n)				((n) * MSC_OFF + 0x2e)
#define MSC_SW_RST_R(n)					((n) * MSC_OFF + 0x2f)
#define MSC_NORMAL_INT_STAT_R(n)			((n) * MSC_OFF + 0x30)
#define MSC_ERROR_INT_STAT_R(n)				((n) * MSC_OFF + 0x32)
#define MSC_NORMAL_INT_STAT_EN_R(n)			((n) * MSC_OFF + 0x34)
#define MSC_ERROR_INT_STAT_EN_R(n)			((n) * MSC_OFF + 0x36)
#define MSC_NORMAL_INT_SIGNAL_EN_R(n)			((n) * MSC_OFF + 0x38)
#define MSC_ERROR_INT_SIGNAL_EN_R(n)			((n) * MSC_OFF + 0x3a)
#define MSC_HOST_CTRL1_R(n)				((n) * MSC_OFF + 0x28)
#define MSC_HOST_CTRL2_R(n)				((n) * MSC_OFF + 0x3e)

/**
 * MSC Register Bit Field Define
 */

/* XFER_MODE_R */
#define MSC_RESP_INT_DISABLE				(1 << 8)
#define MSC_RESP_ERR_CHK_ENABLE				(1 << 7)
#define MSC_MULTI_BLK_SEL				(1 << 5)
#define MSC_DATA_XFER_DIR_RD				(1 << 4)
#define MSC_AUTO_CMD12_ENABLE				(1 << 2)
#define MSC_BLOCK_COUNT_ENABLE				(1 << 1)

/* CMD_R */
#define MSC_RESP_TYPE_SELECT_RESP_NO_RESP		(0 << 0)
#define MSC_RESP_TYPE_SELECT_RESP_LEN_136		(1 << 0)
#define MSC_RESP_TYPE_SELECT_RESP_LEN_48		(2 << 0)
#define MSC_RESP_TYPE_SELECT_RESP_LEN_48B		(3 << 0)
#define MSC_CMD_CRC_CHK_ENABLE				(1 << 3)
#define MSC_CMD_IDX_CHK_ENABLE				(1 << 4)

/* MSC_PSTATE_REG */
#define MSC_CMD_INHIBIT					(1 << 0)
#define MSC_DATA_INHIBIT				(1 << 1)

/* BGAP_CTRL_R */
#define MSC_STOP_BG_REQ					(1 << 0)

/* CLK_CTRL_R */
#define MSC_INTERNAL_CLK_EN				(1 << 0)
#define MSC_SD_CLK_EN					(1 << 2)

/* SW_RST_R */
#define MSC_SW_RST_ALL					(1 << 0)
#define MSC_SW_RST_CMD					(1 << 1)
#define MSC_SW_RST_DAT					(1 << 2)

/* NORMAL_INT_STAT_R */
#define MSC_BUF_RD_READY_STAT				(1 << 5)
#define MSC_XFER_COMPLETE_STAT				(1 << 1)
#define MSC_CMD_COMPLETE_STAT				(1 << 0)

/* NORMAL_INT_STAT_R */
#define MSC_DATA_END_BIT_ERR_STAT			(1 << 6)
#define MSC_DATA_CRC_ERR_STAT				(1 << 5)
#define MSC_DATA_TOUT_ERR_STAT				(1 << 4)
#define MSC_CMD_IDX_ERR_STAT				(1 << 3)
#define MSC_CMD_END_BIT_ERR_STAT			(1 << 2)
#define MSC_CMD_CRC_ERR_STAT				(1 << 1)
#define MSC_CMD_TOUT_ERR_STAT				(1 << 0)


#define MSC_CMDAT_RESPONSE_NONE				(0x0) /* No response */
#define MSC_CMDAT_RESPONSE_R1				(0x1) /* Format R1 , R3, R6, R7 length 48 */
#define MSC_CMDAT_RESPONSE_R1b				(0x2) /* Format R1b length 48 */
#define MSC_CMDAT_RESPONSE_R2				(0x3) /* Format R2 length 136 */
#define MSC_CMDAT_RESPONSE_R3				(0x4) /* Format R3 length 48 */
#define MSC_CMDAT_RESPONSE_R6				(0x7) /* Format R6 length 48 */
#define MSC_CMDAT_RESPONSE_R7				(0x8) /* Format R7 length 48 */

/* HOST_CTRL1_R */
#define MSC_EXT_DAT_XFER_BIT                		(1 << 5)
#define MSC_DAT_XFER_WIDTH_BIT              		(1 << 1)

void sd_init();
int sd_block_read(unsigned int start_blk, unsigned int blk_cnt, void *buf);

#endif	/* __MSC_H__ */
